home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 701-725 / 708 / intuisup / intuisup42.lha / Intuisup / source.lha / Render / render.c < prev    next >
C/C++ Source or Header  |  1992-06-23  |  28KB  |  899 lines

  1. /* $Revision Header *** Header built automatically - do not edit! ***********
  2.  *
  3.  *    (C) Copyright 1991 by Torsten Jürgeleit
  4.  *
  5.  *    Name .....: render.c
  6.  *    Created ..: Thursday 19-Dec-91 15:14:35
  7.  *    Revision .: 8
  8.  *
  9.  *    Date        Author                 Comment
  10.  *    =========   ====================   ====================
  11.  *    23-Jun-92   Torsten Jürgeleit      close_window() now checks if
  12.  *                                       win->UserPort exists before trying
  13.  *                                       to reply all IntuiMessages
  14.  *    22-Jun-92   Torsten Jürgeleit      after modifying NewWindow struct
  15.  *                                       for inner window mode new window
  16.  *                                       dimension is scaled once again in
  17.  *                                       open_window()
  18.  *    12-May-92   Torsten Jürgeleit      text colors for clear_window()
  19.  *    30-Apr-92   Torsten Jürgeleit      raster for clear_window()
  20.  *    26-Apr-92   Torsten Jürgeleit      special algorithm to calc text 2
  21.  *                                         pen for screens with 1 or 2 planes
  22.  *    22-Mar-92   Torsten Jürgeleit      mungwall hit in create_avail_fonts
  23.  *                                            no CopyMem() instead of 2nd
  24.  *                                            AvailFonts() allowed
  25.  *    18-Mar-92   Torsten Jürgeleit      calc inner window dimension BEFORE
  26.  *                                         centering window in open_window()
  27.  *    06-Jan-92   Torsten Jürgeleit      add font support routines
  28.  *    19-Dec-91   Torsten Jürgeleit      Created this file!
  29.  *
  30.  ****************************************************************************
  31.  *
  32.  *    Routines to get information needed to render ISUP objects and some
  33.  *    window support functions
  34.  *
  35.  * $Revision Header ********************************************************/
  36.  
  37.     /* Includes */
  38.  
  39. #include <exec/types.h>
  40. #include <exec/memory.h>
  41. #include <libraries/diskfont.h>
  42. #include <intuition/intuition.h>
  43. #ifdef AZTEC_C
  44. #include <functions.h>   /* needed for Aztec C - prototypes and pragmas for all Amiga system functions */
  45. #endif
  46. #include <libraries/memwatch.h>   /* header file for memory debug link library (Fish 240) - AFTER functions.h */
  47. #include "render.h"
  48.  
  49.     /* Defines */
  50.  
  51. #define RED_SCALE    3    /* amount of RGB values to take in account the different visual impact of those colors */
  52. #define GREEN_SCALE    6
  53. #define BLUE_SCALE    2
  54.  
  55. #define DEFAULT_AVAIL_FONTS_BUFFER_SIZE        1000
  56.  
  57.     /* Statics */
  58.  
  59. STATIC USHORT image_data_arrow_left[] = {   /* bitmap data for left arrow image */
  60.     0x0780, 0x3e00, 0xf800, 0x3e00, 0x0780, 0x0000, 0x0000, 0x0000,
  61.     0x0000, 0x0000
  62. };
  63. STATIC USHORT image_data_arrow_right[] = {   /* bitmap data for right arrow image */
  64.     0xf000, 0x3e00, 0x0f80, 0x3e00, 0xf000, 0x0000, 0x0000, 0x0000,
  65.     0x0000, 0x0000
  66. };
  67. STATIC USHORT image_data_arrow_up[] = {   /* bitmap data for up arrow image */
  68.     0x0800, 0x1c00, 0x3e00, 0x7700, 0xc180, 0x0000, 0x0000, 0x0000,
  69.     0x0000, 0x0000
  70. };
  71. STATIC USHORT image_data_arrow_down[] = {   /* bitmap data for down arrow image */
  72.     0xc180, 0x7700, 0x3e00, 0x1c00, 0x0800, 0x0000, 0x0000, 0x0000,
  73.     0x0000, 0x0000
  74. };
  75. STATIC USHORT image_data_toggle_knob_unselected[] = {   /* bitmap data for unselected toggle knob image */
  76.     0x1ffc, 0x0000, 0x7000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000,
  77.     0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x7000, 0x0000,
  78.     0x1000, 0x0000,   /* Plane 0 */
  79.     0x0002, 0x0000, 0x0003, 0x8000, 0x0000, 0xc000,    0x0000, 0xc000,
  80.     0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000,    0x0003, 0x8000,
  81.     0x0ffe, 0x0000    /* Plane 1 */
  82. };
  83. STATIC USHORT image_data_toggle_knob_selected[] = {   /* bitmap data for selected toggle knob image */
  84.     0x0002, 0x0000, 0x0003, 0x8000, 0x03f0, 0xc000, 0x0ffc, 0xc000,
  85.     0x0ffc, 0xc000, 0x0ffc, 0xc000, 0x03f0, 0xc000, 0x0003, 0x8000,
  86.     0x0ffe, 0x0000,   /* Plane 0 */
  87.     0x1ffc, 0x0000, 0x7000, 0x0000, 0xc3f0, 0x0000,    0xcffc, 0x0000,
  88.     0xcffc, 0x0000, 0xcffc, 0x0000, 0xc3f0, 0x0000,    0x7000, 0x0000,
  89.     0x1000, 0x0000    /* Plane 1 */
  90. };
  91. STATIC USHORT image_data_toggle_check_selected[] = {   /* bitmap data for selected toggle checkmark image */
  92.     0x0038, 0x0060, 0x00c0, 0xe180, 0x7300, 0x3e00, 0x1c00
  93. };
  94. STATIC USHORT image_data_cycle[] = {   /* bitmap data for cycle image */
  95.     0x7f01, 0xc181, 0xc181, 0xc7e1, 0xc3c1, 0xc181, 0xc001,    0xc181,
  96.     0x7f01,   /* Plane 0 */
  97.     0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
  98.     0x0002    /* Plane 1 */
  99. };
  100. STATIC USHORT image_data_count_left[] = {   /* bitmap data for left count image */
  101.     0x0700, 0x3f00, 0xff00, 0x3f00, 0x0700
  102. };
  103. STATIC USHORT image_data_count_right[] = {   /* bitmap data for right count image */
  104.     0xe000, 0xfc00, 0xff00, 0xfc00, 0xe000
  105. };
  106. STATIC struct Image  images[] = {
  107.    {        /* left arrow */
  108.     0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
  109.     &image_data_arrow_left[0], 0, 0, NULL
  110.    }, {        /* right arrow */
  111.     0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
  112.     &image_data_arrow_right[0], 0, 0, NULL
  113.    }, {        /* up arrow */
  114.     0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
  115.     &image_data_arrow_up[0], 0, 0, NULL
  116.    }, {        /* down arrow */
  117.     0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
  118.     &image_data_arrow_down[0], 0, 0, NULL
  119.    }, {        /* toggle select knob unselected */
  120.     0, 0, IMAGE_KNOB_WIDTH, IMAGE_KNOB_HEIGHT, IMAGE_KNOB_DEPTH,
  121.     &image_data_toggle_knob_unselected[0], 0, 0, NULL
  122.    }, {        /* toggle select knob selected */
  123.     0, 0, IMAGE_KNOB_WIDTH, IMAGE_KNOB_HEIGHT, IMAGE_KNOB_DEPTH,
  124.     &image_data_toggle_knob_selected[0], 0, 0, NULL
  125.    }, {        /* toggle select check unselected */
  126.     IMAGE_HORIZ_OFFSET, IMAGE_VERT_OFFSET, IMAGE_CHECK_WIDTH,
  127.     IMAGE_CHECK_HEIGHT, 0, NULL, 0, 0, NULL
  128.    }, {        /* toggle select check selected */
  129.     IMAGE_HORIZ_OFFSET, IMAGE_VERT_OFFSET, IMAGE_CHECK_WIDTH,
  130.     IMAGE_CHECK_HEIGHT, IMAGE_CHECK_DEPTH,
  131.     &image_data_toggle_check_selected[0], 0, 0, NULL
  132.    }, {        /* cycle */
  133.     0, 0, IMAGE_CYCLE_WIDTH, IMAGE_CYCLE_HEIGHT, IMAGE_CYCLE_DEPTH,
  134.     &image_data_cycle[0], 0, 0, NULL
  135.    }, {        /* left count */
  136.     0, 0, IMAGE_COUNT_WIDTH, IMAGE_COUNT_HEIGHT, IMAGE_COUNT_DEPTH,
  137.     &image_data_count_left[0], 0, 0, NULL
  138.    }, {        /* right count */
  139.     0, 0, IMAGE_COUNT_WIDTH, IMAGE_COUNT_HEIGHT, IMAGE_COUNT_DEPTH,
  140.     &image_data_count_right[0], 0, 0, NULL
  141.    }
  142. };
  143. STATIC struct TextAttr  topaz80_attr = { (STRPTR)"topaz.font", TOPAZ_EIGHTY,
  144.                            FS_NORMAL, FPF_ROMFONT };
  145.     /* Static prototypes */
  146.  
  147. SHORT calc_color_level(SHORT color);
  148. VOID  init_render_info_images(struct RenderInfo  *ri);
  149. UBYTE get_image_pixel_color(struct Image  *image, USHORT x, USHORT y);
  150. VOID  set_image_pixel_color(struct Image  *image, USHORT x, USHORT y,
  151.                                    UBYTE color);
  152. BOOL  create_avail_fonts(struct RenderInfo  *ri);
  153. VOID  free_avail_fonts(struct RenderInfo  *ri);
  154.  
  155.     /* Static pragmas */
  156.  
  157. #pragma regcall(calc_color_level(d0))
  158. #pragma regcall(init_render_info_images(a0))
  159. #pragma regcall(get_image_pixel_color(a0,d0,d1))
  160. #pragma regcall(set_image_pixel_color(a0,d0,d1,d2))
  161. #pragma regcall(create_avail_fonts(a0))
  162. #pragma regcall(free_avail_fonts(a0))
  163.  
  164.     /* Get render info for given screen */
  165.  
  166.    struct RenderInfo  *
  167. get_render_info(struct Screen  *screen, USHORT flags)
  168. {
  169.    struct RenderInfo  *ri;
  170.  
  171.    if (ri = AllocMem((LONG)sizeof(struct RenderInfo),
  172.                       (LONG)MEMF_PUBLIC | MEMF_CLEAR)) {
  173.       struct Screen  screen_data;
  174.       USHORT screen_type;
  175.  
  176.       /* Get screen data - if no screen given then use workbench screen */
  177.       if (!screen) {
  178.      screen_type = WBENCHSCREEN;
  179.       } else {
  180.      screen_type = CUSTOMSCREEN;
  181.       }
  182.       if (GetScreenData((BYTE *)&screen_data, (LONG)sizeof(struct Screen),
  183.                        (LONG)screen_type, screen) == TRUE) {
  184.      struct Image  *image;
  185.      USHORT *data;
  186.      ULONG  data_size;
  187.      SHORT  i;
  188.  
  189.      /* Get screen and window data */
  190.      screen                    = &screen_data;
  191.      ri->ri_ScreenWidth        = screen->Width;
  192.      ri->ri_ScreenHeight       = screen->Height;
  193.      ri->ri_ScreenDepth        = screen->RastPort.BitMap->Depth;
  194.      ri->ri_WindowBorderTop    = screen->BarHeight -
  195.                        screen->BarVBorder + screen->WBorTop;
  196.      ri->ri_WindowBorderLeft   = screen->WBorLeft;
  197.      ri->ri_WindowBorderRight  = screen->WBorRight;
  198.      ri->ri_WindowBorderBottom = screen->WBorBottom;
  199.      ri->ri_Flags              = flags;
  200.      ri->ri_ID                 = ISUP_ID;
  201.  
  202.      /* Calc chipmem buffer size for image data */
  203.      for (i = 0, image = &images[0], data_size = 0;
  204.                       i < MAX_RENDER_IMAGES; i++, image++) {
  205.         if (image->ImageData) {
  206.            data_size += (image->Width / 16 + (image->Width & 15 ? 1 : 0))
  207.                    * image->Height * ri->ri_ScreenDepth * 2;
  208.         }
  209.      }
  210.      if (data = AllocMem(data_size,
  211.                   (LONG)MEMF_PUBLIC | MEMF_CHIP | MEMF_CLEAR)) {
  212.         SHORT num_colors;
  213.  
  214.         /* Insert image data buffer and size */
  215.         ri->ri_ImageData     = data;
  216.         ri->ri_ImageDataSize = data_size;
  217.  
  218.         /* Calculate render colors */
  219.         if ((num_colors = 1 << ri->ri_ScreenDepth) > MAX_RENDER_COLORS) {
  220.            num_colors = MAX_RENDER_COLORS;
  221.         }
  222.         if (num_colors < 3) {
  223.  
  224.            /* Set render pens for monochrome screen */
  225.            if (flags & RENDER_INFO_FLAG_BACK_FILL) {
  226.           ri->ri_HighlightPen = 0;
  227.           ri->ri_ShadowPen    = 0;
  228.           ri->ri_TextPen1     = 0;
  229.           ri->ri_TextPen2     = 0;
  230.           ri->ri_BackPen      = 1;
  231.            } else {
  232.           ri->ri_HighlightPen = 1;
  233.           ri->ri_ShadowPen    = 1;
  234.           ri->ri_TextPen1     = 1;
  235.           ri->ri_TextPen2     = 1;
  236.           ri->ri_BackPen      = 0;
  237.            }
  238.         } else {
  239.            struct ColorMap  *cmap;
  240.            SHORT back_color, max_diff, colors[MAX_RENDER_COLORS],
  241.              color_levels[MAX_RENDER_COLORS],
  242.              pens[MAX_RENDER_COLORS];
  243.  
  244.            /* Get current screen colors */
  245.            Forbid();
  246.            for (i = 0, cmap = screen->ViewPort.ColorMap; i < num_colors;
  247.                                       i++) {
  248.           colors[i]       = GetRGB4(cmap, (LONG)i);
  249.           color_levels[i] = calc_color_level(colors[i]);
  250.           pens[i]         = i;
  251.            }
  252.            Permit();
  253.  
  254.            /* Save normal background color */
  255.            back_color = colors[0];
  256.  
  257.            /* Sort colors darkest to brightest (BUBBLE SORT) */
  258.            for (i = 0; i < (num_colors - 1); i++) {
  259.           SHORT j;
  260.  
  261.           for (j = i + 1; j < num_colors; j++) {
  262.              if (color_levels[i] > color_levels[j]) {
  263.             SHORT temp;
  264.  
  265.             /* Swap colors, color levels and pens */
  266.             temp      = colors[i];
  267.             colors[i] = colors[j];
  268.             colors[j] = temp;
  269.  
  270.             temp            = color_levels[i];
  271.             color_levels[i] = color_levels[j];
  272.             color_levels[j] = temp;
  273.  
  274.             temp    = pens[i];
  275.             pens[i] = pens[j];
  276.             pens[j] = temp;
  277.              }
  278.           }
  279.            }
  280.            if (flags & RENDER_INFO_FLAG_BACK_FILL) {
  281.  
  282.           /* Set render pens - highlight pen first */
  283.           ri->ri_HighlightPen = pens[num_colors - 1];   /* use brightest color */
  284.  
  285.           /* Set shadow pen */
  286.           ri->ri_ShadowPen = pens[0];   /* use darkest color */
  287.  
  288.           /* Set back pen */
  289.           i = 1;   /* use 2nd darkest color */
  290.           if (! pens[i]) {   /* don't use normal background color */
  291.              i++;
  292.           }
  293.           ri->ri_BackPen = pens[i];
  294.           back_color     = colors[i];   /* new background color */
  295.            } else {
  296.  
  297.           /* Set render pens - highlight pen first */
  298.           i = num_colors - 1;   /* use brightest color */
  299.           if (! pens[i]) {   /* don't use normal background color */
  300.              i--;
  301.           }
  302.           ri->ri_HighlightPen = pens[i];
  303.  
  304.           /* Set shadow pen */
  305.           i = 0;   /* use darkest color */
  306.           if (! pens[i]) {   /* don't use normal background color */
  307.              i++;
  308.           }
  309.           ri->ri_ShadowPen = pens[i];
  310.  
  311.           /* Set back pen */
  312.           ri->ri_BackPen = 0;
  313.            }
  314.  
  315.            /* Set text pen 1 - use color with greatest difference to
  316.         * back color */
  317.            for (i = 0, max_diff = 0; i < num_colors; i++) {
  318.           SHORT diff;
  319.  
  320.           if ((diff = calc_color_difference(colors[i],
  321.                           back_color)) > max_diff) {
  322.              max_diff        = diff;
  323.              ri->ri_TextPen1 = pens[i];
  324.           }
  325.            }
  326.  
  327.            /* Set text pen 2 - use color with greatest difference to
  328.         * back color and other color than highlight or shadow pen */
  329.            for (i = 0, max_diff = 0; i < num_colors; i++) {
  330.           SHORT diff;
  331.  
  332.           if ((diff = calc_color_difference(colors[i],
  333.                           back_color)) > max_diff) {
  334.              SHORT text1_pen = ri->ri_TextPen1, text2_pen = pens[i];
  335.  
  336.              /* Don't use text 1 pen again */
  337.              if (text2_pen != text1_pen) {
  338.  
  339.             /* Use special algorithm for 1 and 2 bitplanes */
  340.             if (num_colors < 5) {
  341.  
  342.                /* Try to get the pen not used for highlight and
  343.                 * shadow color if this isn't already used for
  344.                 * text 1 color */
  345.                if ((text1_pen != ri->ri_HighlightPen &&
  346.                        text1_pen != ri->ri_ShadowPen) ||
  347.                     (text2_pen != ri->ri_HighlightPen &&
  348.                        text2_pen != ri->ri_ShadowPen)) {
  349.                   max_diff        = diff;
  350.                   ri->ri_TextPen2 = pens[i];
  351.                }
  352.             } else {
  353.  
  354.                /* Try to get the best one from pens not used for
  355.                 * highlight and shadow color */
  356.                if (text2_pen != ri->ri_HighlightPen &&
  357.                         text2_pen != ri->ri_ShadowPen) {
  358.                   max_diff        = diff;
  359.                   ri->ri_TextPen2 = pens[i];
  360.                }
  361.             }
  362.              }
  363.           }
  364.            }
  365.             }
  366.  
  367.         /* Get font and attributes for rendering texts */
  368.         if (!(flags & RENDER_INFO_FLAG_AVAIL_FONTS) ||
  369.                        create_avail_fonts(ri) == TRUE) {
  370.            struct TextFont  *tf;
  371.  
  372.            /* First try to open screen font - if any */
  373.            Forbid();
  374.            if (!screen->Font) {
  375.           tf = NULL;
  376.            } else {
  377.           tf = open_font(ri, screen->Font);
  378.            }
  379.            Permit();
  380.            if (tf) {
  381.           struct TextAttr  *ta = &ri->ri_TextAttr;
  382.  
  383.           /* Build text attribute structure from screen font */
  384.           ta->ta_Name  = (STRPTR)tf->tf_Message.mn_Node.ln_Name;
  385.           ta->ta_YSize = tf->tf_YSize;
  386.           ta->ta_Style = tf->tf_Style;
  387.           ta->ta_Flags = tf->tf_Flags;
  388.            } else {
  389.  
  390.           /* Fall back to TOPAZ80 */
  391.           if (tf = open_font(ri, &topaz80_attr)) {
  392.              CopyMem((BYTE *)&topaz80_attr, (BYTE *)&ri->ri_TextAttr,
  393.                          (LONG)sizeof(struct TextAttr));
  394.           }
  395.            }
  396.            if (ri->ri_TextFont = tf) {
  397.           init_render_info_images(ri);
  398.           return(ri);
  399.            }
  400.            free_avail_fonts(ri);
  401.         }
  402.      }
  403.       }
  404.       FreeMem(ri, (LONG)sizeof(struct RenderInfo));
  405.    }
  406.    return(NULL);
  407. }
  408.     /* Free render info */
  409.  
  410.    VOID
  411. free_render_info(struct RenderInfo  *ri)
  412. {
  413.    if (ri && ri->ri_ID == ISUP_ID) {
  414.       if (ri->ri_TextFont) {
  415.      CloseFont(ri->ri_TextFont);
  416.       }
  417.       free_avail_fonts(ri);
  418.       FreeMem(ri->ri_ImageData, ri->ri_ImageDataSize);
  419.       FreeMem(ri, (LONG)sizeof(struct RenderInfo));
  420.    }
  421. }
  422.     /* Calc color level with specified scaling values */
  423.  
  424.    STATIC SHORT
  425. calc_color_level(SHORT color)
  426. {
  427.    return(calc_color_difference(color, 0));
  428. }
  429.     /* Calc color difference with specified scaling values */
  430.  
  431.    SHORT   /* non static - needed by menus.c too */
  432. calc_color_difference(SHORT color1, SHORT color2)
  433. {
  434.    USHORT temp, diff;
  435.  
  436.    temp  = (color1 & 0x00f) - (color2 & 0x00f);
  437.    diff  = temp * temp * BLUE_SCALE;
  438.    temp  = ((color1 >> 4) & 0x00f) - ((color2 >> 4) & 0x00f);
  439.    diff += temp * temp * GREEN_SCALE;
  440.    temp  = ((color1 >> 8) & 0x00f) - ((color2 >> 8) & 0x00f);
  441.    diff += temp * temp * RED_SCALE;
  442.    return(diff);
  443. }
  444.     /* Init render info images */
  445.  
  446.    STATIC VOID
  447. init_render_info_images(struct RenderInfo *ri)
  448. {
  449.    struct Image  *image_src = &images[0], *image_dest = &ri->ri_Images[0];
  450.    USHORT i, *data = ri->ri_ImageData;
  451.  
  452.    CopyMem((BYTE *)image_src, (BYTE *)image_dest,
  453.               (LONG)(MAX_RENDER_IMAGES * sizeof(struct Image)));
  454.    for (i = 0; i < MAX_RENDER_IMAGES; i++, image_src++, image_dest++) {
  455.  
  456.       /* Set image depth first - needed by pixel functions */
  457.       image_dest->Depth = ri->ri_ScreenDepth;
  458.  
  459.       /* Init image data if any */
  460.       if (image_src->ImageData) {
  461.      USHORT y, width = image_src->Width, height = image_src->Height,
  462.         depth = image_dest->Depth;   /* DEST image depth !!! */
  463.  
  464.      /* Set data buffer ptr */
  465.      image_dest->ImageData = data;
  466.      image_dest->PlanePick = (1 << depth) - 1;
  467.      data += (width / 16 + (width & 15 ? 1 : 0)) * height * depth;
  468.  
  469.      /* Convert image data to current colors */
  470.      for (y = 0; y < height; y++) {
  471.         USHORT x;
  472.  
  473.         for (x = 0; x < width; x++) {
  474.            UBYTE color;
  475.  
  476.            switch(get_image_pixel_color(image_src, x, y)) {
  477.           case 0 :   /* back pen */
  478.              color = ri->ri_BackPen;
  479.              break;
  480.  
  481.           case 1 :   /* highlight pen */
  482.              color = ri->ri_HighlightPen;
  483.              break;
  484.  
  485.           case 2 :   /* shadow pen */
  486.              color = ri->ri_ShadowPen;
  487.              break;
  488.  
  489.           default :   /* special pen */
  490.              color = ri->ri_TextPen2;
  491.              break;
  492.            }
  493.            set_image_pixel_color(image_dest, x, y, color);
  494.         }
  495.      }
  496.       } else {
  497.      UBYTE color;
  498.  
  499.      /* No image data -> monochrome rectangle */
  500.      switch(image_src->PlaneOnOff) {
  501.         case 0 :   /* back pen */
  502.            color = ri->ri_BackPen;
  503.            break;
  504.  
  505.         case 1 :   /* highlight pen */
  506.            color = ri->ri_HighlightPen;
  507.            break;
  508.  
  509.         case 2 :   /* shadow pen */
  510.            color = ri->ri_ShadowPen;
  511.            break;
  512.  
  513.         default :   /* special pen */
  514.            color = ri->ri_TextPen2;
  515.            break;
  516.      }
  517.      image_dest->PlaneOnOff = color;
  518.       }
  519.    }
  520. }
  521.     /* Get color of image pixel */
  522.  
  523.    STATIC UBYTE
  524. get_image_pixel_color(struct Image  *image, USHORT x, USHORT y)
  525. {
  526.    USHORT modulo = image->Width / 16 + (image->Width & 15 ? 1 : 0),
  527.       *data = image->ImageData + y * modulo + x / 16,
  528.       data_offset = image->Height * modulo,
  529.       bit_mask = 0x8000 >> (x & 15);
  530.    UBYTE  i, depth = image->Depth, color_mask = 1, color = 0;
  531.  
  532.    for (i = 0; i < depth; i++, data += data_offset, color_mask <<= 1) {
  533.       if (*data & bit_mask) {
  534.      color |= color_mask;
  535.       }
  536.    }
  537.    return(color);
  538. }
  539.     /* Set color of image pixel */
  540.  
  541.    STATIC VOID
  542. set_image_pixel_color(struct Image  *image, USHORT x, USHORT y, UBYTE color)
  543. {
  544.    USHORT modulo = image->Width / 16 + (image->Width & 15 ? 1 : 0),
  545.       *data = image->ImageData + y * modulo + x / 16,
  546.       data_offset = image->Height * modulo,
  547.       bit_mask = 0x8000 >> (x & 15);
  548.    UBYTE  i, depth = image->Depth;
  549.  
  550.    for (i = 0; i < depth; i++, data += data_offset, color >>= 1) {
  551.       if (color & 1) {
  552.      *data |= bit_mask;
  553.       }
  554.    }
  555. }
  556.     /* Open window */
  557.  
  558.    struct Window *
  559. open_window(struct RenderInfo  *ri, struct NewWindow  *org_nw, USHORT flags)
  560. {
  561.    struct Window  *win = NULL;
  562.  
  563.    if (ri && ri->ri_ID == ISUP_ID && org_nw) {
  564.       struct NewWindow  new_nw, *nw = &new_nw;
  565.       USHORT max_width = ri->ri_ScreenWidth, max_height = ri->ri_ScreenHeight;
  566.  
  567.       /* Duplicate given new window struct */
  568.       CopyMem((BYTE *)org_nw, (BYTE *)nw, (LONG)sizeof(struct NewWindow));
  569.  
  570.       /* Scale new window dimension */
  571.       if (nw->Width > max_width) {
  572.      nw->Width    = max_width;
  573.      nw->LeftEdge = 0;
  574.       } else {
  575.      if ((nw->LeftEdge + nw->Width) > max_width) {
  576.         nw->LeftEdge = max_width - nw->Width;
  577.      }
  578.       }
  579.       if (nw->Height > max_height) {
  580.      nw->Height  = max_height;
  581.      nw->TopEdge = 0;
  582.       } else {
  583.      if ((nw->TopEdge + nw->Height) > max_height) {
  584.         nw->TopEdge = max_height - nw->Height;
  585.      }
  586.       }
  587.  
  588.       /* Change new window struct */
  589.       if (flags & OPEN_WINDOW_FLAG_RENDER_PENS) {
  590.  
  591.      /* Set colors */
  592.      if (ri->ri_Flags & RENDER_INFO_FLAG_BACK_FILL) {
  593.         nw->DetailPen = ri->ri_TextPen1;
  594.         nw->BlockPen  = ri->ri_BackPen;
  595.      } else {
  596.         nw->DetailPen = ri->ri_BackPen;
  597.         nw->BlockPen  = ri->ri_TextPen1;
  598.      }
  599.       }
  600.       if (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW) {
  601.      USHORT hoffset = ri->ri_WindowBorderLeft + ri->ri_WindowBorderRight,
  602.             voffset = ri->ri_WindowBorderTop + ri->ri_WindowBorderBottom;
  603.  
  604.      /* Change width and left edge for inner window dimension */
  605.      if ((nw->Width += hoffset) > max_width) {
  606.         nw->Width    = max_width;
  607.         nw->LeftEdge = 0;
  608.      } else {
  609.         if (nw->LeftEdge > hoffset) {
  610.            nw->LeftEdge -= hoffset;
  611.         } else {
  612.            nw->LeftEdge = 0;
  613.         }
  614.      }
  615.  
  616.      /* Change height and top edge for inner window dimension */
  617.      if ((nw->Height += voffset) > max_height) {
  618.         nw->Height  = max_height;
  619.         nw->TopEdge = 0;
  620.      } else {
  621.         if (nw->TopEdge > voffset) {
  622.            nw->TopEdge -= voffset;
  623.         } else {
  624.            nw->TopEdge = 0;
  625.         }
  626.      }
  627.       }
  628.       if (flags & OPEN_WINDOW_FLAG_CENTER_WINDOW) {
  629.  
  630.      /* Center window AFTER calculation of inner window dimension */
  631.      nw->LeftEdge = (max_width - nw->Width) / 2;
  632.      nw->TopEdge  = (max_height - nw->Height) / 2;
  633.       }
  634.       if (win = OpenWindow(nw)) {
  635.      if (ri->ri_Flags & RENDER_INFO_FLAG_BACK_FILL) {
  636.         clear_window(ri, win, 0, 0, nw->Width, nw->Height, 0);
  637.      }
  638.       }
  639.    }
  640.    return(win);
  641. }
  642.     /* Clear given rectangle of window with data from render info */
  643.  
  644.    VOID
  645. clear_window(struct RenderInfo  *ri, struct Window  *win, USHORT left_edge,
  646.          USHORT top_edge, USHORT width, USHORT height, USHORT flags)
  647. {
  648.    if (ri && ri->ri_ID == ISUP_ID && win) {
  649.       USHORT inner_left, inner_top, inner_width, inner_height,
  650.          ri_flags = ri->ri_Flags;
  651.  
  652.       /* Calc inner window dimension */
  653.       if ((ri_flags & RENDER_INFO_FLAG_INNER_WINDOW) ||
  654.                   (ri_flags & RENDER_INFO_FLAG_BACK_FILL)) {
  655.      inner_left   = ri->ri_WindowBorderLeft;
  656.      inner_top    = ri->ri_WindowBorderTop;
  657.      inner_width  = win->Width - inner_left - ri->ri_WindowBorderRight;
  658.      inner_height = win->Height - inner_top - ri->ri_WindowBorderBottom;
  659.       } else {
  660.      inner_left   = 0;
  661.      inner_top    = 0;
  662.      inner_width  = win->Width;
  663.      inner_height = win->Height;
  664.       }
  665.  
  666.       /* Check if given rectangle fits into inner window */
  667.       if ((SHORT)left_edge >= 0 && (SHORT)top_edge >= 0 && width &&
  668.              height && left_edge < (inner_left + inner_width) &&
  669.                     top_edge < (inner_top + inner_height)) {
  670.      struct RastPort  *rp = win->RPort;
  671.  
  672.      /* Add offsets for inner window to given upper left position */
  673.      if (!(flags & CLEAR_WINDOW_FLAG_ABSOLUTE_POS)) {
  674.         left_edge += inner_left;
  675.         top_edge  += inner_top;
  676.  
  677.         /* Scale upper left position of given rectangle if neccessary */
  678.         if (left_edge < inner_left) {
  679.            left_edge = inner_left;
  680.         }
  681.         if (top_edge < inner_top) {
  682.            top_edge = inner_top;
  683.         }
  684.      }
  685.  
  686.      /* Scale dimension of given rectangle if neccessary */
  687.      if ((SHORT)width <= 0 || (left_edge + width) > (inner_left +
  688.                                  inner_width)) {
  689.         width = inner_left + inner_width - left_edge;
  690.      }
  691.      if ((SHORT)height <= 0 || (top_edge + height) > (inner_top +
  692.                                 inner_height)) {
  693.         height = inner_top + inner_height - top_edge;
  694.      }
  695.  
  696.      /* Set draw mode, colors and fill pattern for using raster */
  697.      if (flags & CLEAR_WINDOW_FLAG_USE_RASTER) {
  698.         STATIC USHORT raster_pattern[] = { 0xaaaa, 0x5555 };
  699.  
  700.         SetDrMd(rp, (LONG)JAM2);
  701.         SetAPen(rp, (LONG)ri->ri_HighlightPen);
  702.         SetBPen(rp, (LONG)ri->ri_BackPen);
  703.         SetAfPt(rp, &raster_pattern[0], 1L);   /* macro !!! */
  704.      } else {
  705.  
  706.         /* Set draw mode */
  707.         if (!(flags & CLEAR_WINDOW_FLAG_CUSTOM_DRAW_MODE)) {
  708.            SetDrMd(rp, (LONG)JAM1);
  709.         }
  710.  
  711.         /* Set fill colors */
  712.         if (!(flags & CLEAR_WINDOW_FLAG_CUSTOM_COLOR)) {
  713.            USHORT apen;
  714.  
  715.            /* Check if special color needed */
  716.            if (flags & CLEAR_WINDOW_FLAG_TEXT1_COLOR) {
  717.           apen = ri->ri_TextPen1;
  718.            } else {
  719.           if (flags & CLEAR_WINDOW_FLAG_TEXT2_COLOR) {
  720.              apen = ri->ri_TextPen2;
  721.           } else {
  722.  
  723.              /* Use background color */
  724.              if ((ri_flags & RENDER_INFO_FLAG_BACK_FILL) &&
  725.                 !(flags & CLEAR_WINDOW_FLAG_NORMAL_COLOR)) {
  726.             apen = ri->ri_BackPen;
  727.              } else {
  728.             apen = 0;
  729.              }
  730.           }
  731.            }
  732.            SetAPen(rp, (LONG)apen);
  733.         }
  734.      }
  735.  
  736.      /* And do clearing window background */
  737.      RectFill(rp, (LONG)left_edge, (LONG)top_edge, (LONG)(left_edge +
  738.                  width - 1), (LONG)(top_edge + height - 1));
  739.  
  740.      /* Clear fill pattern */
  741.      if (flags & CLEAR_WINDOW_FLAG_USE_RASTER) {
  742.         SetAfPt(rp, NULL, 1L);   /* macro !!! */
  743.      }
  744.       }
  745.    }
  746. }
  747.     /* Close window safely, even if shared user port */
  748.  
  749.    VOID
  750. close_window(struct Window  *win, BOOL more_windows)
  751. {
  752.    if (win) {
  753.  
  754.       /* Check if any IDCMP flag used */
  755.       if (win->UserPort) {
  756.      struct IntuiMessage  *msg, *succ;
  757.  
  758.      /* Reply all messages for given window */
  759.      Forbid();
  760.      msg = (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
  761.      while (succ = (struct IntuiMessage *)
  762.                      msg->ExecMessage.mn_Node.ln_Succ) {
  763.         if (more_windows == FALSE || msg->IDCMPWindow == win) {
  764.            Remove((struct Node *)msg);
  765.            ReplyMsg((struct Message *)msg);
  766.         }
  767.         msg = succ;
  768.      }
  769.  
  770.      /* Don't close shared user port */
  771.      if (more_windows == TRUE) {
  772.         win->UserPort = NULL;
  773.         ModifyIDCMP(win, 0L);
  774.      }
  775.      Permit();
  776.       }
  777.       CloseWindow(win);
  778.    }
  779. }
  780.     /* Create list of available fonts - called by create_render_info() */
  781.  
  782.    STATIC BOOL
  783. create_avail_fonts(struct RenderInfo  *ri)
  784. {
  785.    struct AvailFontsHeader  *afh;
  786.    LONG size = DEFAULT_AVAIL_FONTS_BUFFER_SIZE;
  787.    BOOL success = FALSE;
  788.  
  789.    /* Allocate buffer and fill it with data from available fonts */
  790.    if (afh = AllocMem(size, (LONG)MEMF_PUBLIC)) {
  791.       LONG new_size;
  792.  
  793.       if (new_size = AvailFonts((BYTE *)afh, size,
  794.                          (LONG)AFF_MEMORY | AFF_DISK)) {
  795.      /* Allocate larger buffer and try again */
  796.      FreeMem(afh, size);
  797.      size += new_size;
  798.      if (afh = AllocMem(size, (LONG)MEMF_PUBLIC)) {
  799.         AvailFonts((BYTE *)afh, size, (LONG)AFF_MEMORY | AFF_DISK);
  800.      }
  801.       }
  802.  
  803.       /* Save font header in render info data structure */
  804.       ri->ri_AvailFontsHeader     = afh;
  805.       ri->ri_AvailFontsHeaderSize = size;
  806.       success = TRUE;
  807.    }
  808.    return(success);
  809. }
  810.     /* Free list of available fonts - called by free_render_info() */
  811.  
  812.    STATIC VOID
  813. free_avail_fonts(struct RenderInfo  *ri)
  814. {
  815.    if (ri->ri_AvailFontsHeader && ri->ri_AvailFontsHeaderSize) {
  816.       FreeMem(ri->ri_AvailFontsHeader, ri->ri_AvailFontsHeaderSize);
  817.    }
  818. }
  819.     /* Return ptr to list of available fonts */
  820.  
  821.    struct AvailFontsHeader *
  822. avail_fonts(struct RenderInfo  *ri)
  823. {
  824.    struct AvailFontsHeader  *afh = NULL;
  825.  
  826.    if (ri && ri->ri_ID == ISUP_ID &&
  827.                 (ri->ri_Flags & RENDER_INFO_FLAG_AVAIL_FONTS)) {
  828.       afh = ri->ri_AvailFontsHeader;
  829.    }
  830.    return(afh);
  831. }
  832.     /* Check if given font is available and return its correct data */
  833.  
  834.    struct TextAttr *
  835. ask_font(struct RenderInfo  *ri, struct TextAttr  *ta)
  836. {
  837.    struct TextAttr  *best_ta = NULL;
  838.  
  839.    if (ri && ri->ri_ID == ISUP_ID && ta) {
  840.       if (!(ri->ri_Flags & RENDER_INFO_FLAG_AVAIL_FONTS)) {
  841.      best_ta = ta;
  842.       } else {
  843.      struct AvailFontsHeader  *afh = ri->ri_AvailFontsHeader;
  844.      USHORT num = afh->afh_NumEntries;
  845.  
  846.      if (num) {
  847.         struct AvailFonts  *af = (struct AvailFonts *)(afh + 1);
  848.         USHORT search_ysize = ta->ta_YSize, best_ysize = 0;
  849.  
  850.         do {
  851.            struct TextAttr  *avail_ta = &af++->af_Attr;
  852.            int stricmp(const char *_s1, const char *_s2);   /* manually prototyping non ANSI function */
  853.  
  854.            if (!stricmp((BYTE *)avail_ta->ta_Name, (BYTE *)ta->ta_Name)) {
  855.           USHORT avail_ysize = avail_ta->ta_YSize;
  856.  
  857.           if (avail_ysize == search_ysize) {
  858.              best_ta = avail_ta;
  859.              break;
  860.           } else {
  861.              if (avail_ysize < search_ysize) {
  862.             if (avail_ysize > best_ysize) {
  863.                best_ysize = avail_ysize;
  864.                best_ta    = avail_ta;
  865.             }
  866.              } else {
  867.             if (!best_ysize || avail_ysize < best_ysize) {
  868.                best_ysize = avail_ysize;
  869.                best_ta    = avail_ta;
  870.             }
  871.              }
  872.           }
  873.            }
  874.         } while (--num);
  875.      }
  876.       }
  877.    }
  878.    return(best_ta);
  879. }
  880.     /* Open best available text font */
  881.  
  882.    struct TextFont *
  883. open_font(struct RenderInfo  *ri, struct TextAttr  *ta)
  884. {
  885.    struct TextFont  *tf = NULL;
  886.  
  887.    if (ri && ri->ri_ID == ISUP_ID && ta) {
  888.       if (ta = ask_font(ri, ta)) {
  889.      if (!(tf = OpenFont(ta)) || tf->tf_YSize != ta->ta_YSize) {
  890.         if (tf) {
  891.            CloseFont(tf);
  892.         }
  893.         tf = OpenDiskFont(ta);
  894.      }
  895.       }
  896.    }
  897.    return(tf);
  898. }
  899.